package server

import (
	"FileServer/network"
	"FileServer/utils"
	"context"
	"errors"
	"fmt"
	"log"
	"net"
	"net/http"
	"os"
	"os/signal"
	"strconv"
	"strings"
	"syscall"
	"time"

	"github.com/iwen-conf/colorprint/clr"
)

// StartServer 启动文件服务器
func StartServer(initialPort int, absPath string) {

	// 获取目录统计信息
	fileCount, totalSize, err := utils.GetDirStats(absPath)
	if err != nil {
		log.Printf("获取目录统计信息失败: %v", err)
	} else {
		fmt.Println(clr.FGColor("\n📊 目录统计:", clr.Cyan))
		fmt.Printf(clr.FGColor("   - 文件数量: %d\n", clr.Cyan), fileCount)
		fmt.Printf(clr.FGColor("   - 总大小: %.2f MB\n", clr.Cyan), float64(totalSize)/1024/1024)
	}

	// 选择可用端口
	port, err := selectPort(initialPort)
	if err != nil {
		log.Fatalf("无法找到可用端口: %v", err)
	}

	// 创建文件服务器 handler，限制访问路径
	fs := http.FileServer(http.Dir(absPath))
	handler := http.StripPrefix("/", fs)

	// 创建 HTTP 服务器
	server := &http.Server{
		Addr:    ":" + strconv.Itoa(port),
		Handler: handler,
	}

	// 在 goroutine 中启动服务器
	go func() {
		if err = server.ListenAndServe(); err != nil && !errors.Is(err, http.ErrServerClosed) {
			log.Fatalf("服务器启动失败: %v", err)
		}
	}()

	// 显示访问地址
	fmt.Println(clr.FGColor("\n✅ 文件服务器启动成功！", clr.Green))
	fmt.Printf(clr.FGColor("📂 共享目录: %s\n", clr.Cyan), absPath)
	fmt.Printf(clr.FGColor("   - http://localhost:%d (本机访问)\n", clr.Cyan), port)

	// 显示局域网 IP 地址
	localIPs := network.GetLocalIPs()
	if len(localIPs) > 0 {
		fmt.Println(clr.FGColor("\n🔍 局域网地址:", clr.Cyan))
		for _, ip := range localIPs {
			fmt.Printf(clr.FGColor("   - http://%s:%d\n", clr.Cyan), strings.Split(ip, " ")[0], port)
			fmt.Printf(clr.FGColor("     └─ 网卡: %s\n", clr.Yellow), strings.Split(ip, " ")[1])
		}
	}

	fmt.Println(clr.FGColor("\n💡 提示:", clr.Yellow))
	fmt.Println(clr.FGColor("   - 如果某个地址无法访问，请尝试其他地址", clr.Yellow))
	fmt.Println(clr.FGColor("   - 局域网内其他设备请使用对应网卡的IP地址访问", clr.Yellow))
	fmt.Println(clr.FGColor("   - 按 Ctrl+C 可安全停止服务", clr.Yellow))
	fmt.Println(clr.FGColor("   - 文件服务器仅供临时使用，请注意数据安全", clr.Yellow))

	// 等待中断信号
	stop := make(chan os.Signal, 1)
	signal.Notify(stop, os.Interrupt, syscall.SIGTERM)
	<-stop
	log.Println("接收到停止信号，关闭服务器...")

	// 优雅关闭服务器
	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
	defer cancel()
	if err := server.Shutdown(ctx); err != nil {
		log.Printf("服务器关闭出错: %v", err)
	}
	log.Println("服务器已安全关闭")
}

// selectPort 选择一个可用的端口
func selectPort(initialPort int) (int, error) {
	const maxAttempts = 10
	for attempt := 0; attempt < maxAttempts; attempt++ {
		port := initialPort + attempt
		listener, err := net.Listen("tcp", ":"+strconv.Itoa(port))
		if err == nil {
			listener.Close() // 关闭监听器，确保端口可用
			return port, nil
		}
	}
	return 0, fmt.Errorf("在 %d 次尝试后仍无法找到可用端口", maxAttempts)
}
